package no.la58.scribbles.client.uicomponents;

import java.util.logging.Logger;

import no.la58.scribbles.client.services.MessageService;
import no.la58.scribbles.client.services.MessageServiceAsync;
import no.la58.scribbles.shared.Scribble;
import no.la58.scribbles.shared.ScribbleConstants;
import no.la58.scribbles.shared.VoidMethodStatus;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.Widget;

public class ScribbleInput extends Composite {

    private static final String textareaFocusHeight = "70px";
    private static final String textareaBlurHeight = "30px";

    private static ScribbleInputUiBinder uiBinder = GWT.create(ScribbleInputUiBinder.class);

    private static MessageServiceAsync messageService = GWT.create(MessageService.class);

    interface ScribbleInputUiBinder extends UiBinder<Widget, ScribbleInput> {
    }

    private static Logger log = Logger.getLogger(ScribbleInput.class.getName());

    @UiField
    TextArea scribbleText;

    @UiField
    Button cancelButton, broadcastButton;

    @UiField
    Label statusLabel;

    public ScribbleInput() {
	initWidget(uiBinder.createAndBindUi(this));
	scribbleText.setSize("100%", textareaBlurHeight);
    }

    @UiHandler("scribbleText")
    public void resizeOnFocus(FocusEvent event) {
	scribbleText.setSize("100%", textareaFocusHeight);
    }

    @UiHandler("scribbleText")
    public void resizeOnBlur(BlurEvent event) {
	if (scribbleText.getText().length() == 0) {
	    scribbleText.setSize("100%", textareaBlurHeight);
	}
    }

    @UiHandler("scribbleText")
    public void controlSizeOfScribble(KeyUpEvent event) {
	int count = scribbleText.getText().length();
	displayCountOfMessage(count);
    }

    private void displayCountOfMessage(int count) {
	int delta = ScribbleConstants.SCRIBBLE_MAXLENGTH - count;
	String msg = null;
	if (count == 0) {
	    msg = "";
	} else if (delta < 0) {
	    msg = "Thought too long! Shorten your thought with " + (delta) + "characters.";
	} else {
	    msg = delta + " characters left for your thought.";
	}
	setStatus(msg);
    }

    @UiHandler("broadcastButton")
    public void sendMessage(ClickEvent event) {
	String message = scribbleText.getText();
	int count = message.length();
	int delta = ScribbleConstants.SCRIBBLE_MAXLENGTH - count;
	if (delta < 0) {
	    setStatus("Thought is too long to be shared.");
	    return;
	} else if (message.trim().length() == 0) {
	    setStatus("Empty thoughts cannot be shared.");
	    return;
	}
	Scribble scribble = new Scribble(message);
	AsyncCallback<VoidMethodStatus> callback = new AsyncCallback<VoidMethodStatus>() {

	    @Override
	    public void onSuccess(VoidMethodStatus result) {
		switch (result) {
		case SUCCESS:
		    scribbleText.setText("");
		    setStatus("Thought shared.");
		    break;
		case NOT_AUTHENTICATED:
		    setStatus("You must be logged in to share your thoughts.");
		    break;
		case ERROR:
		    log.severe("Error was the response of broadcastScribble()");
		    setStatus("Yikes! (error... mumble, mumble)");
		default:

		    break;
		}
		setEnabled(true);
	    }

	    @Override
	    public void onFailure(Throwable caught) {
		setStatus("Something went wrong when sharing your thought. Think again.");
		setEnabled(true);

		// TODO log to server
	    }
	};
	setEnabled(false);
	messageService.broadcastScribble(scribble, callback);

    }

    @UiHandler("cancelButton")
    public void clearTextArea(ClickEvent event) {
	scribbleText.setText("");
	this.displayCountOfMessage(0);
	scribbleText.setFocus(false);
	resizeOnBlur(null);
    }

    private void setStatus(String status) {
	statusLabel.setText(status);
    }

    private void setEnabled(boolean enabled) {
	scribbleText.setReadOnly(!enabled);
	broadcastButton.setEnabled(enabled);
	cancelButton.setEnabled(enabled);
    }

}
